package com.godenwater.recv.server.sl651;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.filterchain.IoFilterAdapter;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.gov.mwr.sl651.HydroMessage;
import cn.gov.mwr.sl651.IMessage;
import cn.gov.mwr.sl651.IMessageBody;
import cn.gov.mwr.sl651.IMessageHeader;
import cn.gov.mwr.sl651.Symbol;
import cn.gov.mwr.sl651.body.UpBaseBody;
import cn.gov.mwr.sl651.utils.ByteUtil;

public class CommDataHandler extends IoFilterAdapter implements IoHandler {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	private String channel;

	public CommDataHandler(String channel) {
		this.channel = channel;
	}

	/**
	 * 消息接收后的处理，只处理业务逻辑，此消息处理是在解码后，所以只需要关注消息体的内容
	 */
	public void messageReceived(IoSession session, Object message)
			throws Exception {

		logger.info("----------------------------------------------------------------------");
		logger.info("COMM 服务端已收到       消息数;");

		if (message instanceof IoBuffer) {
			System.out.println(">>> HydroServerHandler message is IoBuffer ");
		}

		session.write(message);

		// 启动重发机制

	}

	public void xxxx(byte[] data) {
		int pos = 0;
		byte[] mode = new byte[1];
		System.arraycopy(data, pos, mode, 0, mode.length);
		pos = pos + mode.length;
		int bodyLengthLen = 0;
		int rcrlen = 0;

		IMessageHeader header = null;
		if (mode[0] == (byte) Symbol.SOH_ASC) {
			header = new cn.gov.mwr.sl651.header.AscHeader();
			header.setStartBit(new byte[] { mode[0] });

			// 上行的，中心站地址在前
			byte[] centerAddr = new byte[header.getCenterAddrLen()];
			System.arraycopy(data, pos, centerAddr, 0, centerAddr.length);
			pos = pos + centerAddr.length;
			header.setCenterAddr(centerAddr);

			// 上行的，遥测站地址在前
			byte[] stationAddr = new byte[header.getStationAddrLen()];
			System.arraycopy(data, pos, stationAddr, 0, stationAddr.length);
			pos = pos + stationAddr.length;
			header.setStationAddr(stationAddr);

			byte[] password = new byte[header.getPasswordLen()];
			System.arraycopy(data, pos, password, 0, password.length);
			pos = pos + password.length;
			header.setPassword(password);

			byte[] funcCode = new byte[header.getFuncCodeLen()];
			System.arraycopy(data, pos, funcCode, 0, funcCode.length);
			pos = pos + funcCode.length;
			header.setFuncCode(funcCode);

			byte[] bodyLength = new byte[header.getBodySizeLen()];
			System.arraycopy(data, pos, bodyLength, 0, bodyLength.length);
			pos = pos + bodyLength.length;
			String hexBodyLengthStr = new String(bodyLength);
			byte[] hexBodyLength = ByteUtil.HexStringToBinary(hexBodyLengthStr);
			header.setBodySize(bodyLength);

			byte[] bodyStartBit = new byte[header.getBodyStartBitLen()];
			System.arraycopy(data, pos, bodyStartBit, 0, bodyStartBit.length);
			pos = pos + bodyStartBit.length;
			header.setBodyStartBit(bodyStartBit);
			// System.out.println(">> hexBodyStartBit " +
			// ByteUtil.toHexString(bodyStartBit));

			if (header.getBodyStartBit()[0] == Symbol.SYN) {
				byte[] bodyCount = new byte[header.getBodyCountLen()];
				System.arraycopy(data, pos, bodyCount, 0, bodyCount.length);
				pos = pos + bodyCount.length;
				header.setBodyCount(bodyCount);
			}

			// 转换报文中的上下行标识及报文长度
			bodyLengthLen = parseLength(hexBodyLength);// 需要考虑拆分字节;
			// System.out.println("数据字节长度  " + bodyLengthLen);
			if (bodyStartBit[0] == Symbol.SYN) {
				bodyLengthLen = bodyLengthLen - header.getBodyCountLen();
			}
			rcrlen = 4;

		} else if (mode[0] == (byte) Symbol.SOH_HEX) {
			header = new cn.gov.mwr.sl651.header.HexHeader();
			byte[] startBit = new byte[1];
			System.arraycopy(data, pos, startBit, 0, startBit.length);
			pos = pos + startBit.length;
			header.setStartBit(new byte[] { Symbol.SOH_HEX, Symbol.SOH_HEX });

			// 上行的，中心站地址在前
			byte[] centerAddr = new byte[header.getCenterAddrLen()];
			System.arraycopy(data, pos, centerAddr, 0, centerAddr.length);
			pos = pos + centerAddr.length;
			header.setCenterAddr(centerAddr);

			// 上行的，遥测站地址在前
			byte[] stationAddr = new byte[header.getStationAddrLen()];
			System.arraycopy(data, pos, stationAddr, 0, stationAddr.length);
			pos = pos + stationAddr.length;
			header.setStationAddr(stationAddr);

			byte[] password = new byte[header.getPasswordLen()];
			System.arraycopy(data, pos, password, 0, password.length);
			pos = pos + password.length;
			header.setPassword(password);
			//
			byte[] funcCode = new byte[header.getFuncCodeLen()];
			System.arraycopy(data, pos, funcCode, 0, funcCode.length);
			pos = pos + funcCode.length;
			header.setFuncCode(funcCode);

			byte[] bodyLength = new byte[header.getBodySizeLen()];
			System.arraycopy(data, pos, bodyLength, 0, bodyLength.length);
			pos = pos + bodyLength.length;
			header.setBodySize(bodyLength);

			byte[] bodyStartBit = new byte[header.getBodyStartBitLen()];
			System.arraycopy(data, pos, bodyStartBit, 0, bodyStartBit.length);
			pos = pos + bodyStartBit.length;
			header.setBodyStartBit(bodyStartBit);

			if (bodyStartBit[0] == Symbol.SYN) {
				byte[] bodyCount = new byte[header.getBodyCountLen()];
				System.arraycopy(data, pos, bodyCount, 0, bodyCount.length);
				pos = pos + bodyCount.length;
				header.setBodyCount(bodyCount);
			}

			// 转换报文中的上下行标识及报文长度
			bodyLengthLen = parseLength(bodyLength);// 需要考虑拆分字节;
			if (bodyStartBit[0] == Symbol.SYN) {
				bodyLengthLen = bodyLengthLen - header.getBodyCountLen();
			}
			rcrlen = (mode[0] == Symbol.SOH_ASC) ? 4 : 2;

		} 

		int size = bodyLengthLen + 1 + rcrlen;

		byte[] bodyContent = new byte[bodyLengthLen];// 根据前面header的内容来获取长度
		System.arraycopy(data, pos, bodyContent, 0, bodyContent.length);
		pos = pos + bodyContent.length;
		// 校验码
		byte[] crc = new byte[rcrlen];

		// 终止符
		byte[] eof = new byte[1];
		System.arraycopy(data, pos, eof, 0, eof.length);
		pos = pos + eof.length;

		// 两种协议的CRC校验符与结束符，正好相反
		if ((byte) header.getStartBit()[0] == (byte) 0x68) {
			// 水资源协议
			System.arraycopy(data, pos, crc, 0, crc.length);
			pos = pos + crc.length;
			System.arraycopy(data, pos, eof, 0, eof.length);
			pos = pos + eof.length;

		} else {
			// 水文协议
			System.arraycopy(data, pos, eof, 0, eof.length);
			pos = pos + eof.length;
			System.arraycopy(data, pos, crc, 0, crc.length);
			pos = pos + crc.length;
		}

		// 组装消息
		HydroMessage message = new HydroMessage();
		message.setHeader(header);

		// 根据功能码，构建body体
		IMessageBody body = new UpBaseBody();
		body.setContents(bodyContent);
		message.setBody(body);
		message.setEOF(eof[0]);
		message.setCRC(crc);

	}

	private int parseLength(byte[] bodyLen) {
		byte A1 = (byte) (bodyLen[0] & 0x0f);
		byte A2 = bodyLen[1];
		return ByteUtil.bytesToUshort(new byte[] { A1, A2 });
	}

	/**
	 * 构造回复报文
	 * 
	 * @param msg
	 * @return
	 */
	public IMessage replyMessage(IMessage msg) {
		return null;
	}

	public void viewInfo(IMessage message) {

		System.out.println("******* 中心站查询遥测站实时数据 *******");
		System.out.println("原始包长度：25字节");
		System.out
				.println("原始包信息：7E7E0012345678FFFFFF378008020000130311173540057E13");
		System.out.println("中心站地址：255");
		System.out.println("水文特征码：00，水文测站编码：12345678");
		System.out.println("密码：FFFF");
		System.out.println("功能码：37");
		System.out.println("流水号：0，发报时间：2013-03-11 17:35:40");

	}

	/**
	 * 发送应答式消息
	 */
	public void sendAck(IoSession session) {
		// session.write(message);
	}

	/**
	 * {@inheritDoc}
	 */
	public void sessionClosed(IoSession session) throws Exception {
		logger.info("关闭会话  " + session.getRemoteAddress());
		// HydroServer.getInstance().getSessionManager().removeSession(session);
	}

	/**
	 * 当session创建连接后，需添加到一个客户端中
	 */
	public void sessionCreated(IoSession session) throws Exception {
		logger.info("创建会话  " + session.getRemoteAddress());
		String log = "创建会话  " + session.getRemoteAddress();
		// HydroServer.getInstance().getLogManager().addLog(log);
		// HydroServer.getInstance().getSessionManager().createSession(session);
	}

	/**
	 * {@inheritDoc}
	 */
	public void sessionIdle(IoSession session, IdleStatus status)
			throws Exception {
		logger.info("空闲会话  " + session.getRemoteAddress());

	}

	/**
	 * {@inheritDoc}
	 */
	public void sessionOpened(IoSession session) throws Exception {
		logger.info("Session Opened...");

	}

	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		session.close(true);

		// logger.info("会话出现异常  " + session.getRemoteAddress() + " \t"
		// + cause.getMessage());
		// cause.printStackTrace();
		// IoSessionLogger sessionLogger = IoSessionLogger.getLogger(session,
		// logger);
		logger.info(
				"会话出现异常  " + session.getRemoteAddress() + " \t"
						+ cause.getMessage(), cause);

	}

	/**
	 * 消息应答事件
	 */
	public void messageSent(IoSession session, Object message) throws Exception {
		// TODO Auto-generated method stub
		logger.info("应答会话  " + session.getRemoteAddress());
		// session.close(true);
	}

	public void inputClosed(IoSession arg0) throws Exception {
		// TODO Auto-generated method stub
		
	}
}
